import json
import os
from datetime import datetime
import time
from decimal import Decimal
from alipay import AliPay
from django import http
from django.conf import settings
from django.contrib.auth.mixins import LoginRequiredMixin
from django.shortcuts import render
# Create your views here.
from django.views import View
from django_redis import get_redis_connection
from apps.goods.models import SKU
from apps.orders.models import OrderInfo, OrderGoods
from apps.users.models import Address
from meiduo_mall.settings.dev import logger
from utils.response_code import RETCODE




class OrderSuccessView(View):
    def get(self, request):
        order_id = request.GET.get('order_id')
        pay_method = request.GET.get('pay_method')
        payment_amount = request.GET.get('payment_amount')

        context = {
            "order_id": order_id,
            'pay_method': pay_method,
            "payment_amount": payment_amount
        }
        print(context)
        return render(request, 'order_success.html', context)


class OrderCommitView(LoginRequiredMixin, View):
    def post(self, request):

        # 1.接收参数 地址id  支付方式
        json_dict = json.loads(request.body.decode())
        address_id = json_dict.get('address_id')
        pay_method = json_dict.get('pay_method')

        # 2.校验
        try:
            address = Address.objects.get(id=address_id)
        except Address.DoesNotExist:
            return http.HttpResponseForbidden('address_id无效!')

        if pay_method not in [OrderInfo.PAY_METHODS_ENUM['CASH'], OrderInfo.PAY_METHODS_ENUM['ALIPAY']]:
            return http.HttpResponseForbidden('暂不支持这种支付方式!')

        # 3. 订单表---生成订单号---时间戳 +9位+ user_id
        user = request.user
        order_id = datetime.now().strftime('%Y%m%d%H%M%S') + "%09d" % user.id
        # 1.开启事务
        from django.db import transaction
        with transaction.atomic():
            # 事务开始的标记
            save_id = transaction.savepoint()

            try:
                # 4. 创建订单表数据(单个)
                order = OrderInfo.objects.create(
                    order_id=order_id,
                    user=user,
                    address=address,

                    total_count=0,
                    total_amount=Decimal('0.00'),

                    freight=Decimal('10.00'),
                    pay_method=pay_method,
                    status=OrderInfo.ORDER_STATUS_ENUM['UNPAID'] if pay_method == OrderInfo.PAY_METHODS_ENUM[
                        'ALIPAY'] else
                    OrderInfo.ORDER_STATUS_ENUM['UNSEND']
                )
                # 从购物车 取出 选中的商品
                redis_client = get_redis_connection('carts')
                carts_data = redis_client.hgetall(user.id)
                carts_dict = {}
                for key, value in carts_data.items():
                    sku_id = int(key.decode())
                    sku_dict = json.loads(value.decode())

                    if sku_dict['selected']:
                        carts_dict[sku_id] = sku_dict

                sku_ids = carts_dict.keys()
                for sku_id in sku_ids:

                    while True:
                        sku = SKU.objects.get(id=sku_id)

                        # 1.记录 商品的老库存  和 老销量
                        original_stock = sku.stock
                        original_sales = sku.sales

                        # 判断库存 , 如果库存 小于 购买个数 ; 购买失败
                        cart_count = carts_dict[sku_id]['count']

                        if cart_count > sku.stock:
                            # 事务回滚
                            transaction.savepoint_rollback(save_id)
                            return http.JsonResponse({'code': RETCODE.STOCKERR, 'errmsg': '库存不足'})

                        # time.sleep(10)
                        # sku 库存减少  销量增加
                        # sku.stock -= cart_count
                        # sku.sales += cart_count
                        # sku.save()
                        new_stcok = original_stock - cart_count
                        new_sales = original_sales + cart_count

                        # 加乐观锁
                        result = SKU.objects.filter(id=sku_id, stock=original_stock).update(stock=new_stcok, sales=new_sales)

                        #  如果库存是足够的 --购买失败了--继续购买--直到成功为止(或者库存不足才失败)
                        if result == 0:
                            continue

                        # spu 销量增加
                        sku.spu.sales += cart_count
                        sku.spu.save()

                        # 5. 创建订单商品数据(多个)
                        OrderGoods.objects.create(
                            order_id=order_id,
                            sku=sku,
                            count=cart_count,
                            price=sku.price
                        )

                        # 总个数 和 总金额(没运费)
                        order.total_count += cart_count
                        order.total_amount += sku.price * cart_count

                        # 下单成功跳出
                        break

                # 加运费 总金额
                order.total_amount += order.freight
                order.save()

                # 清空购物车购买的数据
                redis_client.hdel(user.id, *carts_dict)

            except Exception as e:
                logger.error(e)
                # 暴力回滚
                transaction.savepoint_rollback(save_id)
                return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '下单失败'})

            # 4张表都没有问题 提交事务
            transaction.savepoint_commit(save_id)

        # 6. 返回响应对象
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '下单成功', 'order_id': order.order_id})


class OrderSettlementView(LoginRequiredMixin, View):
    def get(self, request):
        user = request.user
        try:
            addresses = Address.objects.filter(user = user, is_deleted=False)
        except Exception as e:
            addresses = None
        redis_client = get_redis_connection('carts')
        carts_data = redis_client.hgetall(user.id)
        carts_dict = {}
        for key,value in carts_data.items():
            sku_key = int(key.decode())
            sku_dict = json.loads(value.decode())
            if sku_dict['selected']:
                carts_dict[sku_key] = sku_dict
        skus = SKU.objects.filter(id__in = carts_dict.keys())
        total_count = 0
        total_amount = Decimal('0.00')
        for sku in skus:
            sku.count = carts_dict[sku.id]['count']
            sku.amount = sku.price * sku.count
            total_count += sku.count
            total_amount += sku.price * carts_dict[sku.id]['count']
        freight = Decimal('10.00')
        # 4.构建前端显示的数据
        context = {
            'addresses': addresses,
            'skus': skus,
            'total_count': total_count,
            'total_amount': total_amount,
            'freight': freight,
            'payment_amount': total_amount + freight,
            'default_address_id': user.default_address_id
        }
        return render(request, 'place_order.html', context)
        # return render(request, 'place_order.html')











# class OrderCommitView(LoginRequiredMixin, View):
#     def post(self, request):
#         json_dict = json.loads(request.body.decode())
#         address_id = json_dict.get('address_id')
#         pay_method = json_dict.get('pay_method')
#         try:
#             address = Address.objects.get(id=address_id)
#         except Address.DoesNotExist:
#             return http.HttpResponseForbidden('address_id无效!')
#
#         if pay_method not in [OrderInfo.PAY_METHODS_ENUM['CASH'], OrderInfo.PAY_METHODS_ENUM['ALIPAY']]:
#             return http.HttpResponseForbidden('暂不支持这种支付方式!')
#         user = request.user
#         order_id = datetime.now().strftime('%Y%m%d%H%M%S') + "%09d" % user.id
#         from django.db import transaction
#         with transaction.atomic():
#             save_id = transaction.savepoint()
#             try:
#                 order = OrderInfo.objects.create(
#                     order_id=order_id,
#                     user=user,
#                     address=address,
#                     total_count=0,
#                     total_amount=Decimal('0.00'),
#                     freight=Decimal('10.00'),
#                     pay_method=pay_method,
#                     status=OrderInfo.ORDER_STATUS_ENUM['UNPAID'] if pay_method == OrderInfo.PAY_METHODS_ENUM[
#                         'ALIPAY'] else
#                     OrderInfo.ORDER_STATUS_ENUM['UNSEND']
#                 )
#                 redis_client = get_redis_connection('carts')
#                 carts_data = redis_client.hgetall(user.id)
#                 carts_dict = {}
#                 for key, value in carts_data.items():
#                     sku_id = int(key.decode())
#                     sku_dict = json.loads(value.decode())
#                     if sku_dict['selected']:
#                         carts_dict[sku_id] = sku_dict
#                 sku_ids = carts_dict.keys()
#                 for sku_id in sku_ids:
#                     while True:
#                         sku = SKU.objects.get(id=sku_id)
#
#                         original_stock = sku.stock
#                         original_sales = sku.sales
#                         cart_count = carts_dict[sku_id]['count']
#                         if cart_count > sku.stock:
#                             transaction.savepoint_rollback(save_id)
#                             return http.JsonResponse({'code': RETCODE.STOCKERR, 'errmsg': '库存不足'})
#                         new_stcok = original_stock - cart_count
#                         new_sales = original_sales + cart_count
#                         result = SKU.objects.filter(id=sku_id, stock=original_stock).update(stock=new_stcok, sales=new_sales)
#                         if result == 0:
#                             continue
#                         sku.spu.sales += cart_count
#                         sku.spu.save()
#                         OrderGoods.objects.create(
#                             order_id=order_id,
#                             sku=sku,
#                             count=cart_count,
#                             price=sku.price
#                         )
#                         order.total_count += cart_count
#                         order.total_amount += sku.price * cart_count
#                         break
#                 order.total_amount += order.freight
#                 order.save()
#                 redis_client.hdel(user.id, *carts_dict)
#             except Exception as e:
#                 logger.error(e)
#                 transaction.savepoint_rollback(save_id)
#                 return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '下单失败'})
#             transaction.savepoint_commit(save_id)
#         return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '下单成功', 'order_id': order.order_id})
# class OrderSettlementView(LoginRequiredMixin, View):
#     def get(self, request):
#         user = request.user
#         try:
#             addresses = Address.objects.filter(user = user, is_deleted=False)
#         except Exception as e:
#             addresses = None
#         redis_client = get_redis_connection('carts')
#         carts_data = redis_client.hgetall(user.id)
#         carts_dict = {}
#         for key,value in carts_data.items():
#             sku_key = int(key.decode())
#             sku_dict = json.loads(value.decode())
#             if sku_dict['selected']:
#                 carts_dict[sku_key] = sku_dict
#         skus = SKU.objects.filter(id__in = carts_dict.keys())
#         total_count = 0
#         total_amount = Decimal('0.00')
#         for sku in skus:
#             sku.count = carts_dict[sku.id]['count']
#             sku.amount = sku.price * sku.count
#             total_count += sku.count
#             total_amount += sku.price * carts_dict[sku.id]['count']
#         freight = Decimal('10.00')
#         # 4.构建前端显示的数据
#         context = {
#             'addresses': addresses,
#             'skus': skus,
#             'total_count': total_count,
#             'total_amount': total_amount,
#             'freight': freight,
#             'payment_amount': total_amount + freight,
#             'default_address_id': user.default_address_id
#         }
#         return render(request, 'place_order.html', context)